/*
 * @Author: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git
 * @Date: 2025-05-10 22:09:53
 * @LastEditors: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git
 * @LastEditTime: 2025-06-07 22:43:21
 * @FilePath: /udp_echo_server/UdpServer.hpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#pragma once

#include <iostream>

#include<unistd.h>
#include<string>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>



#include"Log.hpp"
#include "nocopy.hpp"

using namespace log_ns;
static const int gsockfd=-1;
static const uint16_t glocalport=8888;

enum
{
    SOCKET_ERROR=1,
    BIND_ERROR
};

class UdpServer : public nocopy
{

public:
    UdpServer(const std::string& localip,uint16_t localport=glocalport)
    :_sockfd(gsockfd)
    ,_localport(localport)
    ,_localip(localip)
    ,_isrunning(false)
    {
        
    }
    void InitServer()// 在初始化里里面创建：socket
    {
        // 1、创建socket文件
        _sockfd=::socket(AF_INET,SOCK_DGRAM,0);
        if(_sockfd<0)
        {
            LOG(FATAL,"socket error\n");
            exit(SOCK_DGRAM);
        }
        LOG(DEBUG,"socket create success,_sokket: %d\n",_sockfd);


        // 2、绑定（ip和port）
        struct sockaddr_in local;
        memset(&local,0,sizeof(local));
        local.sin_family=AF_INET;
        local.sin_port=htons(_localport);//htons是将一个“端口号 ”转化为“网络序列”的函数
        // Udpserver user(" 192.1.1.1",8899); 这种字符串风格的ip
        local.sin_addr.s_addr=inet_addr(_localip.c_str());// 这个函数：inet_addr的功能是将“字符串风格的ip”转化为“4字节的网络序列ip”

        int n=::bind(_sockfd,(struct sockaddr*)&local,sizeof(local));
        if(n<0)
        {
            LOG(FATAL,"bind error\n");
            exit(BIND_ERROR);
        }
        LOG(DEBUG,"bind create success\n");

    }

    void Start()
    {
        _isrunning=true;
        char inbuffer[1024];
        while(_isrunning)
        {
            struct sockaddr_in peer;
            socklen_t len=sizeof(peer);
            ssize_t n=recvfrom(_sockfd,inbuffer,sizeof(inbuffer)-1,0,(struct sockaddr*)&peer,&len);
            if(n>0)
            {
                inbuffer[n]=0;
                std::cout<<" client say#"<<inbuffer<<std::endl;
                std::string echo_string=" [udp_server echo] #";
                
                echo_string+=inbuffer;
                sendto(_sockfd,echo_string.c_str(),echo_string.size(),0,(struct sockaddr*)&peer,len);
            }
        }
    }

    ~UdpServer()
    {
        if(_sockfd>gsockfd) ::close(_sockfd);
    }
private:
    int _sockfd;
    int _localport;
    std::string _localip;
    bool _isrunning;
};